package com.yeyks.commonReference.service.consumer.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Maps;
import com.yeyks.account.dal.domain.AccountInfo;
import com.yeyks.common.ajax.AjaxResponseBody;
import com.yeyks.common.appcommon.dto.platform.AppFishBallGoodsDTO;
import com.yeyks.common.appcommon.json.JsonFishExtraInfo;
import com.yeyks.common.appcommon.param.platform.QueryFishBallGoodsParam;
import com.yeyks.common.appcommon.result.CommonPage;
import com.yeyks.common.appcommon.result.CommonResult;
import com.yeyks.common.base.PageInfo;
import com.yeyks.common.dto.FishBallGoodsDTO;
import com.yeyks.common.em.FishBallEnum;
import com.yeyks.common.em.ResponseStatus;
import com.yeyks.common.exception.ServiceException;
import com.yeyks.common.param.fishball.AddFishBallGoodsParam;
import com.yeyks.common.param.fishball.UpdateFishBallGoodsParam;
import com.yeyks.common.utils.ObjectConvertUtil;
import com.yeyks.common.utils.RedisUtil;
import com.yeyks.commonReference.pojo.param.consumer.FishBallGoodsConversionParam;
import com.yeyks.commonReference.service.account.AccountInfoService;
import com.yeyks.commonReference.service.consumer.FishBallGoodsService;
import com.yeyks.commonReference.service.consumer.UserCouponInfoService;
import com.yeyks.consumer.dal.dao.FishBallGoodsMapper;
import com.yeyks.consumer.dal.domain.FishBall;
import com.yeyks.consumer.dal.domain.FishBallGoods;
import com.yeyks.consumer.dal.domain.FishBallGoodsMessage;
import com.yeyks.consumer.dal.domain.UserInfo;
import com.yeyks.consumer.service.FishBallGoodsMessageService;
import com.yeyks.consumer.service.FishBallService;
import com.yeyks.other.dal.dao.CouponInfoMapper;
import com.yeyks.other.dal.domain.CouponInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.yeyks.common.utils.apputil.bean.MyBeanUtils.convertCommonPageList;


/**
 * <p>
 * 鱼宝可兑换的商品表 服务实现类
 * </p>
 *
 * @author yun
 * @since 2019-06-25
 */
@Service
@Slf4j
public class FishBallGoodsServiceImpl extends ServiceImpl<FishBallGoodsMapper, FishBallGoods> implements FishBallGoodsService {

    @Autowired
    private FishBallGoodsMapper fishBallGoodsMapper;

    @Autowired
    private AccountInfoService accountService;

    @Autowired
    private CouponInfoMapper couponInfoMapper;

    @Autowired
    private FishBallService fishBallService;
    @Autowired
    private UserCouponInfoService userCouponService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private FishBallGoodsMessageService fishBallGoodsMessageService;


    @Override
    public ResponseEntity<AjaxResponseBody> list(Integer pageNum, Integer pageSize, AccountInfo loginUser) {

        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            log.info("当前操作人" + loginUser.getName());
            int count = fishBallGoodsMapper.selectCount(new QueryWrapper<FishBallGoods>().eq(FishBallGoods.DELETE_FLAG, "0"));
            List<FishBallGoods> fishBallGoodList = fishBallGoodsMapper.selectPage2((pageNum - 1) * pageSize, pageSize);
            List<FishBallGoodsDTO> fishBallGoodsDTOList = ObjectConvertUtil.convertList(fishBallGoodList, FishBallGoodsDTO.class);
            assert fishBallGoodsDTOList != null;
            fishBallGoodsDTOList.stream().forEach(fishBallGoodsDTO ->
            {
                fishBallGoodsDTO.setImages(this.getImages(fishBallGoodsDTO.getImage()));
                fishBallGoodsDTO.setCouponName(this.getCoupon(fishBallGoodsDTO.getCouponId()));
                fishBallGoodsDTO.setImageDes(this.getImageDes(fishBallGoodsDTO.getExtraInfo()));
            });
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("count", count);
            resultMap.put("list", fishBallGoodsDTOList);
            responseBody.setBody(resultMap);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    @Transactional
    @Override
    public ResponseEntity<AjaxResponseBody> save(AddFishBallGoodsParam param, AccountInfo loginUser) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {

            if (null != param) {
                log.info("当前操作人" + loginUser.getName());
                //查询券的总数量，判断商品数量是否超过券的总数量
                if (param.getType() == 2) {
                    //商品价格和详情图不能为空
                    /*if (null == param.getPrice()) {
                        throw new ServiceException("鱼宝商品价格不能为空");
                    }
                    if (StringUtils.isEmpty(param.getExtraInfo())) {
                        throw new ServiceException("鱼宝商品详情图片不能为空");
                    }*/
                    log.info("执行商品添加");
                } else {
                    if (param.getCouponId() == null) {
                        throw new ServiceException("券ID不能为空");
                    }
                    CouponInfo couponInfo = couponInfoMapper.selectByPrimaryKey(param.getCouponId());
                    if (null == couponInfo) {
                        responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
                        responseBody.setMsg("优惠券ID不存在");
                        return ResponseEntity.ok(responseBody);
                    }
                    if (param.getCount() == null || param.getCount() < 0 || couponInfo.getCount() < param.getCount()) {
                        param.setCount(couponInfo.getCount());
                    }
                }
                FishBallGoods fishBallGoods = ObjectConvertUtil.convertObject(param, FishBallGoods.class);
                //默认鱼宝商品未删除
                fishBallGoods.setDeleteFlag(0);
                fishBallGoods.setStatus(1);
                fishBallGoods.setOperatorId(loginUser.getId());
                //组装图片信息
                JsonFishExtraInfo extraInfo = new JsonFishExtraInfo();
                if (!StringUtils.isEmpty(param.getExtraInfo())) {
                    List<String> imageList = Arrays.asList(param.getExtraInfo().split(","));
                    extraInfo.setImageList(imageList);
                    fishBallGoods.setExtraInfo(JSON.toJSONString(extraInfo));
                }
                int count = fishBallGoodsMapper.insert(fishBallGoods);
                if (count > 0) {
                    responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
                    responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
                }
            }
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }
        return ResponseEntity.ok(responseBody);
    }

    @Transactional
    @Override
    public ResponseEntity<AjaxResponseBody> update(UpdateFishBallGoodsParam updateFishBallGoodsParam, AccountInfo loginUser) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {

            if (null != updateFishBallGoodsParam) {
                AccountInfo operatorInfo = accountService.token2AccountInfo(updateFishBallGoodsParam.getToken());
                log.info("当前操作人" + operatorInfo.getName());
                FishBallGoods fishBallGoods = ObjectConvertUtil.convertObject(updateFishBallGoodsParam, FishBallGoods.class);
                assert fishBallGoods != null;
                fishBallGoods.setOperatorId(operatorInfo.getId());
                int count = fishBallGoodsMapper.updateById(fishBallGoods);
                if (count > 0) {
                    responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
                    responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
                } else {
                    responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
                    responseBody.setMsg(ResponseStatus.RS_FAIL.getMsg());
                }
            }
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }
        return ResponseEntity.ok(responseBody);
    }

    @Override
    public ResponseEntity<AjaxResponseBody> enable(AccountInfo loginUser, Integer id, Integer status) {

        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            log.info("当前操作人" + loginUser.getName());
            FishBallGoods fishBallGoods = fishBallGoodsMapper.selectByPrimaryKey(id);
            if (fishBallGoods != null && !status.equals(fishBallGoods.getStatus())) {

                fishBallGoods.setStatus(status);
                fishBallGoods.setOperatorId(loginUser.getId());
                int count = fishBallGoodsMapper.updateById(fishBallGoods);
                if (count > 0) {
                    responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
                    responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
                }
            } else {
                responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
                responseBody.setMsg(ResponseStatus.RS_FAIL.getMsg());
            }
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }
        return ResponseEntity.ok(responseBody);
    }

    @Override
    public ResponseEntity<AjaxResponseBody> delete(AccountInfo loginUser, Integer id) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            log.info("当前操作人" + loginUser.getName());
            FishBallGoods fishBallGoods = fishBallGoodsMapper.selectByPrimaryKey(id);
            if (fishBallGoods != null) {
                fishBallGoods.setDeleteFlag(1);
                fishBallGoods.setOperatorId(loginUser.getId());
                int count = fishBallGoodsMapper.updateById(fishBallGoods);
                if (count > 0) {
                    responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
                    responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
                }
            } else {
                responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
                responseBody.setMsg(ResponseStatus.RS_FAIL.getMsg());
            }
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }
        return ResponseEntity.ok(responseBody);
    }

    @Override
    public CommonResult<CommonPage<AppFishBallGoodsDTO>> selectPageByParam(QueryFishBallGoodsParam param, AccountInfo accountInfo) {

        CommonPage<AppFishBallGoodsDTO> appFishBallGoodsDTOCommonPage = new CommonPage<>();
        PageHelper.startPage(param.getPageNum(), param.getPageSize());
        List<FishBallGoods> fishBallGoodsList = fishBallGoodsMapper.selectList(new QueryWrapper<FishBallGoods>()
                .eq(FishBallGoods.DELETE_FLAG, 0));
        if (!CollectionUtils.isEmpty(fishBallGoodsList)) {
            Map<Integer, CouponInfo> couponInfoMap = Maps.newHashMap();
            List<Integer> couponIds = fishBallGoodsList.stream().map(FishBallGoods::getCouponId).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(couponIds)) {
                List<CouponInfo> couponInfos = couponInfoMapper.selectBatchIds(couponIds);
                couponInfoMap = couponInfos.stream().collect(Collectors.toMap(CouponInfo::getId,
                        Function.identity(), (key1, key2) -> key2));
            }
            CommonPage<FishBallGoods> commonPage = CommonPage.restPage(param.getPageNum(), param.getLastId(), fishBallGoodsList);
            appFishBallGoodsDTOCommonPage = convertCommonPageList(commonPage, AppFishBallGoodsDTO.class);
            //存入优惠券
            for (AppFishBallGoodsDTO appFishBallGoodsDTO : appFishBallGoodsDTOCommonPage.getList()) {
                CouponInfo couponInfo = couponInfoMap.get(appFishBallGoodsDTO.getCouponId());
                if (couponInfo != null) {
                    appFishBallGoodsDTO.setCouponName(couponInfo.getTitle());
                }
            }
        }

        return CommonResult.success(appFishBallGoodsDTOCommonPage);
    }

    /**
     * 图片转换
     *
     * @param image 图片字符串
     * @return
     */
    private List<String> getImages(String image) {
        String[] str = image.split(",");
        return Arrays.asList(str);
    }

    /**
     * 获取图片详情
     *
     * @param extraInfo 宽展信息
     * @return 返回结果
     */
    private List<String> getImageDes(String extraInfo) {

        JsonFishExtraInfo fishExtraInfo = JSON.parseObject(extraInfo, JsonFishExtraInfo.class);
        if (null != fishExtraInfo && !CollectionUtils.isEmpty(fishExtraInfo.getImageList())) {
            return fishExtraInfo.getImageList();
        }
        return null;
    }

    private String getCoupon(Integer id) {

        CouponInfo couponInfo = couponInfoMapper.selectByPrimaryKey(id);

        if (couponInfo != null) {
            return couponInfo.getTitle();
        }
        return "优惠券";
    }

    /**
     * 消费商品券
     *
     * @param userInfo
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer conversion(UserInfo userInfo, FishBallGoodsConversionParam param) {
        return redisUtil.runWithLock("lock:com.yeyks.commonReference.service.consumer.FishBallGoodsService", () -> {
            Integer id = param.getId();
            try {
                FishBall fishBall = fishBallService.getFishBallNoCreate(userInfo.getId());
                if (fishBall == null) {
                    log.info("该用户鱼宝账号为空userId = {}", userInfo.getId());
                    throw new ServiceException("该用户鱼宝账号为空");
                }
                //根据券id获取商品券
                FishBallGoods fishBallGoods = baseMapper.selectByPrimaryId(id);
                if (fishBallGoods == null) {
                    log.info("没有该商品id = {}", id);
                    throw new ServiceException("没有该商品");
                }
                switch (fishBallGoods.getType()) {
                    case 0:
                        break;
                    case 2:
                        if (StrUtil.isBlank(param.getReceiveName())
                                || StrUtil.isBlank(param.getReceiveAddress())
                                || StrUtil.isBlank(param.getReceivePhone())) {
                            throw new ServiceException("参数错误");
                        }
                        break;
                    default:
                        break;
                }
                int totelAmount = fishBall.getTotalAmount() == null ? 0 : fishBall.getTotalAmount();
                int useAmount = fishBall.getUseAmount() == null ? 0 : fishBall.getUseAmount();
                int remainAmount = totelAmount - useAmount;
                int count = fishBallGoods.getNeedFishballCount() == null ? 0 : fishBallGoods.getNeedFishballCount();
                if (remainAmount < count) {
                    log.info("账户鱼宝不足remain = {}, count = {}", remainAmount, count);
                    throw new ServiceException("账户鱼宝不足");
                }
                int goodsCount = fishBallGoods.getCount() == null ? 0 : fishBallGoods.getCount();
                if (goodsCount == 0) {
                    log.info("该商品已兑完id = {}", id);
                    throw new ServiceException("该商品已兑完");
                }
                switch (fishBallGoods.getType()) {
                    case 0:
                        Integer couponId = fishBallGoods.getCouponId();
                        Boolean flag = userCouponService.userGetFishBallCoupon(userInfo.getId(), couponId);
                        if (!flag) {
                            log.info("用户领取券异常{}{}", userInfo.getId(), couponId);
                            throw new ServiceException("用户领取券异常");
                        }
                        break;
                    case 2:
                        FishBallGoodsMessage fishBallGoodsMessage = BeanUtil.toBean(param, FishBallGoodsMessage.class);
                        fishBallGoodsMessage.setGoodsId(param.getId());
                        fishBallGoodsMessage.setUserId(userInfo.getId());
                        fishBallGoodsMessageService.save(fishBallGoodsMessage);
                        break;
                    default:
                        break;
                }
                //减少商品总数
                int newGoodsCount = goodsCount - 1 < 0 ? 0 : goodsCount - 1;
                fishBallGoods.setCount(newGoodsCount);
                fishBallGoods.setGmtModified(new Date());
                int res = baseMapper.updateById(fishBallGoods);
                if (res != 1) {
                    log.info("更新商品的个数异常");
                    throw new ServiceException("更新商品异常");
                }
                return fishBallService.descFishBall(count, userInfo.getId(), FishBallEnum.GOODS.desc(), 2);
            } catch (ServiceException e) {
                log.error("消费商品券异常aa{}", e.getLocalizedMessage());
                throw e;
            } catch (Exception e) {
                log.error("消费商品券异常{}", e.getLocalizedMessage());
                e.printStackTrace();
                throw e;
            }
        });
    }

    /**
     * 分页获取商品券
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public List<FishBallGoodsDTO> list(Integer pageNo, Integer pageSize) {
        PageInfo of = PageInfo.of(pageNo, pageSize);
        Map<String, Object> map = new HashMap<>();
        map.put("limit", of.getLimit());
        map.put("offset", of.getOffset());
        List<FishBallGoods> fishBallGoods = baseMapper.list(map);
        return getFishBallGoodsDTO(fishBallGoods);
    }

    private List<FishBallGoodsDTO> getFishBallGoodsDTO(List<FishBallGoods> fishBallGoods) {
        List<FishBallGoodsDTO> fishBallGoodsDTOS = new ArrayList<>();
        for (FishBallGoods fishBallGood : fishBallGoods) {
            FishBallGoodsDTO fishBallGoodsDTO = ObjectConvertUtil.convertObject(fishBallGood, FishBallGoodsDTO.class);
            fishBallGoodsDTOS.add(fishBallGoodsDTO);
        }
        return fishBallGoodsDTOS;
    }

}
